import cx from 'classnames';
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
import Button from '../../../Button';
import Space from '../../../Space';
import { DisplayTable } from '../index';

import { prefix } from '../../../config';
import { useDebounce } from '../../../hooks';
import { getPrefixCls } from '../../../utils';
import {
  defaultPopModalStyle,
  defaultRowKey,
  defaultTableSizeConfig,
  SELECT_POP_MODAL,
} from '../../config';
import TableContext, { createContext, UPDATE_STATE } from '../../context/table';
import * as utils from '../../utils';
import { caculateColumnMargin } from '../../utils';

import type { Context } from '../../context/table';
import type { AnyObject, DisplayTableProps } from '../../type';

export interface Props<T extends AnyObject> extends DisplayTableProps<T> {
  visible?: boolean;
  width?: number;
  context?: React.Context<Context<T>>;
  positionStyle?: React.CSSProperties;
  onConfirm?: (selectedRows: T[]) => void;
  onCancel?: () => void;
}

const prefixCls = getPrefixCls(prefix.editableTable, 'select-pop-modal');
function TablePopModal<T extends AnyObject>(props: Props<T>) {
  const { id, visible, rowKey = defaultRowKey, pagination, context } = props;
  const {
    size = 'middle',
    columns = [],
    dataSource = [],
    rowSelection,
  } = props;
  const {
    table: tableContextInfo,
    table: { scroll: popModalScroll },
    dispatch,
  } = useContext<Context<T>>(context);
  const debouncedPopModalScroll = useDebounce(popModalScroll, { wait: 10 });

  const modalRef = useRef<any>();
  const tableRef = useRef<any>();

  useEffect(() => {
    const requestOffset = 100;
    const { scrollTop, scrollHeight, clientHeight } = debouncedPopModalScroll;
    if (
      scrollTop > 0 &&
      scrollHeight - clientHeight - scrollTop < requestOffset &&
      pagination
    ) {
      const { current: page, pageSize: size, total } = pagination;
      page * size < total && onChangePagination(page + 1, size);
    }
  }, [
    debouncedPopModalScroll.scrollTop,
    debouncedPopModalScroll.scrollHeight,
    popModalScroll.clientHeight,
  ]);

  const onChangePagination = (
    page: number,
    size: number,
    params?: AnyObject,
  ) => {
    props.onChangePagination && props.onChangePagination(page, size, params);
  };
  const onConfirm = () => {
    if (tableRef.current) {
      const data = tableRef.current.getSelectedRows();
      props.onConfirm && props.onConfirm(data);
    }
  };
  const onCancel = () => {
    props.onCancel && props.onCancel();
  };
  const onClickDocument = (e: any) => {
    if (visible && modalRef.current && !e.path.includes(modalRef.current)) {
      onCancel();
    }
  };

  const tableProps: DisplayTableProps<T> = {
    id,
    rowKey,
    columns,
    dataSource,
    isCanSetting: true,
    isCanResizeColumn: false,
    pagination: false,
    size,
    context,
    defaultStatus: { size: 'small' },
    rowSelection,
  };
  useEffect(() => {
    const payload: any = { isShowPopModal: visible };
    if (!tableContextInfo.name) payload.name = SELECT_POP_MODAL;
    dispatch({ type: UPDATE_STATE, payload });
  }, [tableContextInfo.name, visible]);

  useEffect(() => {
    window.addEventListener('click', onClickDocument);
    return () => window.removeEventListener('click', onClickDocument);
  }, [visible, modalRef.current]);
  return visible ? (
    <>
      <div
        ref={modalRef}
        className={cx(`${prefixCls}`, { show: visible })}
        style={{ ...defaultPopModalStyle, ...props.positionStyle }}
      >
        <div className={cx(`${prefixCls}__table`)}>
          <DisplayTable
            {...tableProps}
            ref={tableRef}
            onChangePagination={props.onChangePagination}
          />
        </div>
        <div className={cx(`${prefixCls}__footer`)}>
          <Space>
            <Button onClick={onCancel}>取消</Button>
            <Button type="primary" onClick={onConfirm}>
              确认
            </Button>
          </Space>
        </div>
      </div>
      {/* <div className={`${prefixCls}__table--mark`} onClick={onCancel}></div> */}
    </>
  ) : null;
}

export function TablePopModalContext<T extends AnyObject>(props: Props<T>) {
  const { context, ...restProps } = props;
  const tableId = useMemo(
    () => props.id || utils.createTableId('table'),
    [props.id],
  );
  const tableContext = useMemo(() => createContext(), [tableId]);
  const tableProps = { ...restProps, id: tableId };
  if (context) {
    return <TablePopModal {...tableProps} context={context} />;
  } else {
    return (
      <TableContext context={tableContext}>
        <TablePopModal {...tableProps} context={tableContext} />
      </TableContext>
    );
  }
}

function EditableTablePopModal<T extends AnyObject>(props: Props<T>) {
  const { context, size = 'middle', ...restProps } = props;
  const {
    table: {
      size: editableTableSize,
      curOperateInfo,
      columnPinning,
      style: tableStyle,
      scroll: editableTableScroll,
      columns: visibleFlatColumns,
    },
  } = useContext<Context<T>>(context); // 编辑表格context
  const [positionStyle, setPositionStyle] = useState<React.CSSProperties>({});

  const getPositionStyle = () => {
    const style: React.CSSProperties = { ...positionStyle };
    const { rowIndex, columnId, meta } = curOperateInfo;
    if (meta.editType !== 'modal') return style;
    const { thead, tbody } = defaultTableSizeConfig[editableTableSize];
    const { scrollTop } = editableTableScroll;
    const info = caculateColumnMargin({
      columnId,
      scroll: editableTableScroll,
      columnPinning,
      visibleFlatColumns,
    });
    let alignKey = 'left';
    if (info.left + defaultPopModalStyle.width > (tableStyle.width as number)) {
      alignKey = 'right';
    }
    if (info.right > (tableStyle.width as number)) {
      alignKey = 'left';
    }
    style[alignKey] = info[alignKey];

    let top = thead + (rowIndex + 1) * tbody - scrollTop;
    if (
      top + defaultPopModalStyle.height >
      Math.floor(Number(tableStyle.maxHeight) + defaultPopModalStyle.height / 3)
    ) {
      top = top - tbody - defaultPopModalStyle.height;
    }
    style.top = top;

    return style;
  };

  useEffect(() => {
    const style = getPositionStyle();
    setPositionStyle(style);
  }, [
    defaultTableSizeConfig,
    visibleFlatColumns,
    curOperateInfo,
    tableStyle,
    editableTableScroll,
    columnPinning,
  ]);

  const popModalProps = { ...restProps, positionStyle, size };
  return <TablePopModalContext {...popModalProps} />;
}
export default EditableTablePopModal;
